package com.ywu.api.standard.service;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.ywu.boot.context.YwuContext;
import com.ywu.boot.context.YwuContextHolder;
import com.ywu.common.constant.CommonConstant;
import com.ywu.common.entity.PageList;
import com.ywu.common.page.PageService;
import com.ywu.common.result.CommonResult;
import com.ywu.gateway.spi.dto.GatewayRouteRedisDto;
import com.ywu.gateway.spi.dto.GatewayRouterDto;
import com.ywu.gateway.spi.spi.GatewaySpi;
import com.ywu.api.standard.data.ApiRouterRepository;
import com.ywu.api.standard.dto.ApiRouterDto;
import com.ywu.api.standard.entity.ApiRouterEntity;
import com.ywu.role.spi.dto.ApiRoleAuthDto;
import com.ywu.role.spi.spi.UserRoleAuthSpi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName GatewayRouterService
 * @Description TODO
 * @Author GroundDemo
 * @Date 2024/1/28 17:56
 * @Version 1.0
 **/
@Service
@Slf4j
public class ApiRouterService {
    @Autowired
    private ApiRouterRepository apiRouterRepository;

    @Autowired
    private GatewaySpi gatewaySpi;

    @Autowired
    private UserRoleAuthSpi userRoleAuthSpi;

    /**
     * @Author GroundDemo
     * @Description 刷新路由
     * @Date 21:38 2024/2/15
     * @Param []
     * @return void
     **/
    @Async
    public void refreshRoute() {
        // 删除缓存中的内容
        gatewaySpi.reloadRoute();
    }

    /**
     * @Author GroundDemo
     * @Description 添加路由
     * @Date 21:26 2024/2/15
     * @Param [apiRouterDto]
     * @return com.ywu.blog.common.result.CommonResult<java.lang.Object>
     **/
    public CommonResult<Object> addRoute(ApiRouterDto apiRouterDto) {
        // 校验路由是否存在
        ApiRouterEntity apiRouterEntity = new ApiRouterEntity();
        apiRouterEntity.setCode(apiRouterDto.getCode());
        ApiRouterEntity routeEntity = apiRouterRepository.getRouteEntity(apiRouterEntity);
        if (Objects.isNull(routeEntity) || StringUtils.isBlank(routeEntity.getId())) {
            add(apiRouterDto);
            com.ywu.api.spi.dto.ApiRouterDto spiDto = new com.ywu.api.spi.dto.ApiRouterDto();
            BeanUtils.copyProperties(apiRouterDto, spiDto);
            gatewaySpi.addApiRouteCacheInfo(spiDto);
            return CommonResult.success(null);
        }
        return CommonResult.error().setMessage("route has exist").setCode(CommonConstant.ERROR_CODE);
    }

    /**
     * @Author GroundDemo
     * @Description 修改路由
     * @Date 21:35 2024/2/15
     * @Param [apiRouterDto]
     * @return com.ywu.blog.common.result.CommonResult<java.lang.Object>
     **/
    public CommonResult<Object> updateRoute(ApiRouterDto apiRouterDto) {
        // 校验路由是否存在
        ApiRouterEntity apiRouterEntity = new ApiRouterEntity();
        apiRouterEntity.setId(apiRouterDto.getId());
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        apiRouterEntity.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        ApiRouterEntity routeEntity = apiRouterRepository.getRouteEntity(apiRouterEntity);
        if (Objects.isNull(routeEntity) || StringUtils.isBlank(routeEntity.getId())) {
            return CommonResult.error().setMessage("route not exist").setCode(CommonConstant.ERROR_CODE);
        }
        update(apiRouterDto);
        com.ywu.api.spi.dto.ApiRouterDto spiDto = new com.ywu.api.spi.dto.ApiRouterDto();
        BeanUtils.copyProperties(apiRouterDto, spiDto);
        gatewaySpi.addApiRouteCacheInfo(spiDto);
        return CommonResult.success(null);
    }

    /**
     * @Author GroundDemo
     * @Description 删除路由
     * @Date 21:36 2024/2/15
     * @Param [apiRouterDto]
     * @return com.ywu.blog.common.result.CommonResult<java.lang.Object>
     **/
    public CommonResult<Object> deleteRoute(ApiRouterDto apiRouterDto) {
        if (StringUtils.isNotBlank(apiRouterDto.getId())) {
            // 查询判断是否存在
            ApiRouterEntity apiRouterEntity = new ApiRouterEntity().setId(apiRouterDto.getId());
            YwuContext currentContext = YwuContextHolder.getCurrentContext();
            apiRouterEntity.setTenantId(currentContext.getYwuContextTenant().getTenantId());
            ApiRouterEntity routeEntity = apiRouterRepository.getRouteEntity(apiRouterEntity);
            if (Objects.isNull(routeEntity) || StringUtils.isBlank(routeEntity.getId())) {
                return CommonResult.success(null);
            }
            delete(routeEntity.getId());
            // 删除API的授权信息
            ApiRoleAuthDto apiRoleAuthDto = new ApiRoleAuthDto();
            apiRoleAuthDto.setApiId(Integer.parseInt(routeEntity.getId()));
            userRoleAuthSpi.apiRoleAuthDeleteInfo(apiRoleAuthDto);
            GatewayRouterDto gatewayRouterDto = new GatewayRouterDto();
            gatewayRouterDto.setCode(routeEntity.getCode());
            gatewaySpi.delete(gatewayRouterDto);
        }
        return CommonResult.success(null);
    }

    public Integer add(ApiRouterDto apiRouterDto) {
        ApiRouterEntity apiRouterEntity = new ApiRouterEntity();
        BeanUtils.copyProperties(apiRouterDto, apiRouterEntity);
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        apiRouterEntity.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        if (StringUtils.isNotBlank(apiRouterDto.getId())) {
            apiRouterEntity.updateInfo(currentContext.getYwuContextUser().getUserAccount());
            return apiRouterRepository.updateByPrimaryKeySelective(apiRouterEntity);
        }
        apiRouterEntity.createInfo(currentContext.getYwuContextUser().getUserAccount());
        return apiRouterRepository.insertSelective(apiRouterEntity);
    }

    public Integer update(ApiRouterDto apiRouterDto) {
        ApiRouterEntity apiRouterEntity = new ApiRouterEntity();
        BeanUtils.copyProperties(apiRouterDto, apiRouterEntity);
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        apiRouterEntity.updateInfo(currentContext.getYwuContextUser().getUserAccount());
        return apiRouterRepository.updateByPrimaryKeySelective(apiRouterEntity);
    }

    public Integer delete(String id) {
        return apiRouterRepository.deleteByPrimaryKey(id);
    }

    /**
    * @Author GroundDemo
    * @Description 根据条件查询路由列表
    * @Date 21:21 2024/2/28
    * @Param [apiRouterDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> apiRouteInfoQuery(ApiRouterDto apiRouterDto) {
        // 设置租户ID
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        if (Objects.isNull(currentContext) || Objects.isNull(currentContext.getYwuContextTenant())) {
            apiRouterDto.setTenantId(null);
        } else {
            apiRouterDto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        }
        PageList<ApiRouterEntity> pageListRes = new PageList<>();
        // 查询数量
        Integer count = apiRouterRepository.getRouteEntitiesCount(apiRouterDto);
        PageService.execPageStartAndEnd(apiRouterDto.getPageInfo());
        List<ApiRouterEntity> routeEntities = apiRouterRepository.getRouteEntities(apiRouterDto);
        pageListRes.setPageIndex(apiRouterDto.getPageInfo().getPageIndex());
        pageListRes.setPageSize(apiRouterDto.getPageInfo().getPageSize());
        pageListRes.setDataList(routeEntities);
        pageListRes.setRecordCount(count);
        return CommonResult.success(pageListRes);
    }

    /**
    * @Author GroundDemo
    * @Description 查询API的redis缓存
    * @Date 22:03 2024/2/29
    * @Param [apiRouterDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> apiRouteRedisCacheInfo(ApiRouterDto apiRouterDto) {
        // 先根据条件查询出route数据
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        apiRouterDto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        List<ApiRouterEntity> routeEntities = apiRouterRepository.getRouteInfoNoPage(apiRouterDto);
        Map<String, String> collect = new HashMap<>();
        for (ApiRouterEntity entity : routeEntities) {
            collect.put(entity.getCode(), entity.getApplicationName());
        }
        CommonResult<List<GatewayRouteRedisDto>> result = gatewaySpi.apiRouteRedisCacheInfo(new GatewayRouterDto());
        if (!StringUtils.equals("200", result.getCode())) {
            return CommonResult.error().setCode(result.getCode()).setErrorCode(result.getErrorCode())
                    .setMessage(result.getMessage());
        }
        List<GatewayRouteRedisDto> res = result.getData();
        List<GatewayRouteRedisDto> filterRes = new ArrayList<>();
        // 填充微服务名称
        for (GatewayRouteRedisDto redisDto : res) {
            if (collect.containsKey(redisDto.getId())) {
                redisDto.setApplicationName(collect.get(redisDto.getId()));
                filterRes.add(redisDto);
            }
        }
        List<GatewayRouteRedisDto> resultDto = filterRes.stream().filter(item -> StringUtils.isBlank(apiRouterDto.getCode()) || item.getId().contains(apiRouterDto.getCode()))
                .filter(item -> StringUtils.isBlank(apiRouterDto.getApplicationName()) || apiRouterDto.getApplicationName().equals(item.getApplicationName()))
                .collect(Collectors.toList());
        return CommonResult.success(resultDto);
    }

    /**
    * @Author GroundDemo
    * @Description 根据条件查询路由
    * @Date 19:56 2024/8/10
    * @Param [apiRouterDto]
    * @return com.ywu.common.result.CommonResult<com.ywu.api.standard.entity.ApiRouterEntity>
    **/
    public CommonResult<ApiRouterEntity> apiRouteInfoQueryForSpi(ApiRouterDto apiRouterDto) {
        // 判断code字段是否为空
        if (StringUtils.isBlank(apiRouterDto.getCode())) {
            CommonResult<ApiRouterEntity> error = CommonResult.error();
            return error.setErrorCode("api.code.is.blank").setMessage("API编码不能为空");
        }
        // 回去上下文中的租户ID
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        if (Objects.nonNull(currentContext) && Objects.nonNull(currentContext.getYwuContextTenant().getTenantId())) {
            apiRouterDto.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        }
        ApiRouterEntity entityByCode = apiRouterRepository.getEntityByCode(apiRouterDto);
        return CommonResult.success(entityByCode);
    }

    /**
    * @Author GroundDemo
    * @Description 更新API租户共享状态
    * @Date 14:24 2024/8/18
    * @Param [apiRouterDto]
    * @return com.ywu.common.result.CommonResult<com.ywu.api.standard.entity.ApiRouterEntity>
    **/
    public CommonResult<ApiRouterEntity> apiRouteUpdateShareInfo(ApiRouterDto apiRouterDto) {
        apiRouterRepository.updateCommonTypeById(apiRouterDto);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 查询所有注册的api信息 - 网关调用
    * @Date 19:04 2025/3/17
    * @Param []
    * @return com.ywu.common.result.CommonResult<java.util.List<com.ywu.api.standard.entity.ApiRouterEntity>>
    **/
    public CommonResult<List<ApiRouterEntity>> queryAllRoutesSpi() {
        List<ApiRouterEntity> apiRouterEntities = apiRouterRepository.queryAllRoutes();
        if (Objects.isNull(apiRouterEntities)) {
            apiRouterEntities = new ArrayList<>();
        }
        return CommonResult.success(apiRouterEntities);
    }

    /**
    * @Author GroundDemo
    * @Description 批量根据code查询数据
    * @Date 14:16 2025/3/24
    * @Param [apiRouterDto]
    * @return com.ywu.common.result.CommonResult<java.util.List<com.ywu.api.standard.entity.ApiRouterEntity>>
    **/
    public CommonResult<List<ApiRouterEntity>> queryApiByCode(List<ApiRouterDto> apiRouterDto) {
        if (CollectionUtils.isEmpty(apiRouterDto)) {
            return CommonResult.success(new ArrayList<>());
        }
        List<ApiRouterEntity> entityList = apiRouterRepository.queryByCodes(apiRouterDto);
        if (CollectionUtils.isEmpty(entityList)) {
            entityList = new ArrayList<>();
        }
        return CommonResult.success(entityList);
    }
}